package com.qingzhu.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.qingzhu.dao.LoginDao;
import com.qingzhu.dao.UserDao;
import com.qingzhu.dao.impl.LoginDaoImpl;
import com.qingzhu.dao.impl.UserDaoImpl;
import com.qingzhu.pojo.Login;
import com.qingzhu.pojo.User;
import com.qingzhu.util.Md5Util;
import com.qingzhu.util.RandomString;

import java.util.Calendar;
import java.util.Date;

public class LoginAndRegisterServiceImpl implements com.qingzhu.service.LoginAndRegisterService {
    LoginDao loginDao = new LoginDaoImpl();
    UserDao userDao = new UserDaoImpl();

    @Override
    public int toRegister(User user) {
        // 先插入用户信息，因为需要获取到用户的自增id
        int insertUserResult = userDao.insertUser(user);
        /* 封装登录信息 密码使用MD5加密储存 */
        Login login = new Login();
        login.setUserId(user.getId());
        login.setUserName(user.getUserName());
        login.setPassword(user.getPassword());
        // 获取随机的字符串
        String randomString = RandomString.getRandomString(10);
        login.setMdStr(randomString);
        // 将密码和随机的字符串进行拼接并使用MD5对拼接后的结果进行加密
        String newPass = Md5Util.getPassword(login.getPassword()+randomString);
        login.setMdPassWord(newPass);
        int insertLoginResult = loginDao.insertLogin(login);
        return insertLoginResult>0 && insertUserResult>0 ? 1 : 0;
    }

    @Override
    public Login login(String nameOrPhone, String password) {
        // 先根据用户名登录，如果根据用户名没有找到登录信息就根据手机号登录
        Login login = loginDao.login(nameOrPhone);
        if (login == null) {
            User user = userDao.findUserFromPhone(nameOrPhone);
            if (user != null) {
                login = loginDao.loginFromUserId(user.getId());
            }
        }
        // 如果最终都没有查找到用户信息，就提示用户不存在
        if (login != null) {
            // 如果账号被锁定，将判断账号是否满足解锁要求；如果未被锁定将判断用户密码是否正确
            if (login.getAccountState() == 1) {
                login.setLoginCode(3);
                // 获取账号锁定的时间节点
                Date lockTime = login.getLockTime();
                // 获取当前的时间节点
                Calendar calendar = Calendar.getInstance();
                Date currentTime = calendar.getTime();
                // 计算账号锁定的时长，如果大于5分钟就解锁
                long between = DateUtil.between(lockTime, currentTime, DateUnit.MINUTE);
                long lockSunTime = 30;
                if (between < lockSunTime) {
                    login.setMessage("您的账号已经被锁定！锁定状态将在"+(lockSunTime-between)+"分钟后自动解除");
                }else {
                    // 自动解锁账号
                    login = endLock(login);
                    login = isLogin(login,password);
                }
            }else {
                login = isLogin(login,password);
            }
        }else {
            login = new Login();
            login.setLoginCode(1);
            login.setMessage("用户名或手机号可能不存在！");
        }
        return login;
    }

    // 密码输入错误时的执行逻辑，如果错误超过3次将会锁定账号
    private Login loginError(Login login) {
        // 获取该账号密码输入错误的次数并加1
        int failNumber = login.getFailNumber();
        login.setFailNumber(failNumber+1);
        // 计算剩余重试机会
        int effectiveNum = 3-login.getFailNumber();
        if (effectiveNum > 0) {
            loginDao.updateLock(login);
            login.setMessage("您的密码输入有误！请确认后重试。您还剩余"+effectiveNum+"次重试机会");
        }else {
            // 锁定账号
            login.setAccountState(1);
            // 记录账号的锁定时间
            Calendar calendar = Calendar.getInstance();
            login.setLockTime(calendar.getTime());
            // 更新数据库中账号的状态
            loginDao.updateLock(login);
            login.setMessage("您的账号已经被锁定，请30分钟后重试");
        }
        return login;
    }
    // 将账号的所有异常参数恢复到初始值
    private Login endLock(Login login) {
        login.setAccountState(0);
        login.setLockTime(null);
        login.setFailNumber(0);
        loginDao.updateLock(login);
        return login;
    }
    // 判断用户密码是否正确
    private Login isLogin(Login login, String password) {
        // 获取加密后的密码和拼接的字符串
        String loginPassword = login.getMdPassWord();
        String mdStr = login.getMdStr();
        // 将用户输入的密码和取出的字符串拼接并进行MD5加密，将加密后的结果与查询后的密码进行比较
        if (loginPassword.equals(Md5Util.getPassword(password+mdStr))) {
            User user = userDao.findById(login.getUserId());
            login.setNiceName(user.getNickName());
            login.setLoginCode(0);
            // 初始化账号的状态
            endLock(login);
        }else {
            login.setLoginCode(2);
            // 判断账号是否需要被锁定
            login = loginError(login);
        }
        return login;
    }
}
